home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacWorld 1999 May
/
Macworld (1999-05).dmg
/
Updaters
/
SpriteWorld 2.2.1 Update
/
Source Updates
/
SpriteLayer.c
< prev
next >
Wrap
Text File
|
1999-02-15
|
16KB
|
617 lines
///--------------------------------------------------------------------------------------
// SpriteLayer.c
//
// Portions are copyright: © 1991-94 Tony Myles, All rights reserved worldwide.
//
// Description: implementation of the sprite layers
///--------------------------------------------------------------------------------------
#ifndef __SWCOMMON__
#include "SWCommonHeaders.h"
#endif
#ifndef __MEMORY__
#include <Memory.h>
#endif
#ifndef __SPRITEWORLDUTILS__
#include "SpriteWorldUtils.h"
#endif
#ifndef __SPRITEWORLD__
#include "SpriteWorld.h"
#endif
#ifndef __SPRITELAYER__
#include "SpriteLayer.h"
#endif
#ifndef __SPRITE__
#include "Sprite.h"
#endif
///--------------------------------------------------------------------------------------
// SWCreateSpriteLayer
///--------------------------------------------------------------------------------------
SW_FUNC OSErr SWCreateSpriteLayer(
SpriteLayerPtr *spriteLayerP)
{
OSErr err;
SpriteLayerPtr tempSpriteLayerP;
err = noErr;
*spriteLayerP = NULL;
tempSpriteLayerP = (SpriteLayerPtr)NewPtrClear((Size)sizeof(SpriteLayerRec));
if (tempSpriteLayerP != NULL)
{
tempSpriteLayerP->tileLayer = 10;
tempSpriteLayerP->isPaused = false;
*spriteLayerP = tempSpriteLayerP;
}
else
{
err = MemError();
}
SWSetStickyIfError( err );
return err;
}
///--------------------------------------------------------------------------------------
// SWDisposeSpriteLayer
///--------------------------------------------------------------------------------------
SW_FUNC void SWDisposeSpriteLayer(
SpriteLayerPtr *spriteLayerPP)
{
SpriteLayerPtr spriteLayerP = *spriteLayerPP;
if (spriteLayerP != NULL)
{
DisposePtr((Ptr)spriteLayerP);
*spriteLayerPP = NULL;
}
}
///--------------------------------------------------------------------------------------
// SWAddSprite
///--------------------------------------------------------------------------------------
SW_FUNC OSErr SWAddSprite(
SpriteLayerPtr spriteLayerP,
SpritePtr newSpriteP)
{
SpritePtr tailSpriteP = spriteLayerP->tailSpriteP;
OSErr err = noErr;
SW_ASSERT(spriteLayerP != NULL);
SW_ASSERT(newSpriteP != NULL);
if (newSpriteP->parentSpriteLayerP != NULL)
err = kSpriteAlreadyInLayer;
if (err == noErr)
{
// attach the new sprite to the end of the list
// or make it the head if the list is empty.
if (tailSpriteP != NULL)
tailSpriteP->nextSpriteP = newSpriteP;
else
spriteLayerP->headSpriteP = newSpriteP;
// link up the new sprite in both directions
newSpriteP->prevSpriteP = tailSpriteP;
newSpriteP->nextSpriteP = NULL;
// make the new sprite the tail
spriteLayerP->tailSpriteP = newSpriteP;
// mark the sprite to be drawn, in case the sprite changed tile layers
newSpriteP->needsToBeDrawn = true;
// Store the parentSpriteLayer in the Sprite
newSpriteP->parentSpriteLayerP = spriteLayerP;
}
SWSetStickyIfError( err );
return err;
}
///--------------------------------------------------------------------------------------
// SWRemoveSprite
///--------------------------------------------------------------------------------------
SW_FUNC OSErr SWRemoveSprite(
SpritePtr oldSpriteP)
{
SpriteLayerPtr spriteLayerP;
OSErr err = noErr;
SW_ASSERT(oldSpriteP != NULL);
spriteLayerP = oldSpriteP->parentSpriteLayerP;
if (spriteLayerP == NULL)
err = kBadParameterErr;
if (err == noErr)
{
// is this not the tail sprite?
if (oldSpriteP->nextSpriteP != NULL)
{
// link the next sprite to the prev sprite
oldSpriteP->nextSpriteP->prevSpriteP = oldSpriteP->prevSpriteP;
}
else
{
// make the prev sprite the tail
spriteLayerP->tailSpriteP = oldSpriteP->prevSpriteP;
}
// is this not the head sprite?
if (oldSpriteP->prevSpriteP != NULL)
{
// link the prev sprite to the next sprite
oldSpriteP->prevSpriteP->nextSpriteP = oldSpriteP->nextSpriteP;
}
else
{
// make the next sprite the first sprite
spriteLayerP->headSpriteP = oldSpriteP->nextSpriteP;
}
oldSpriteP->parentSpriteLayerP = NULL;
}
SWSetStickyIfError( err );
return err;
}
///--------------------------------------------------------------------------------------
// SWRemoveAllSpritesFromLayer
///--------------------------------------------------------------------------------------
SW_FUNC void SWRemoveAllSpritesFromLayer(
SpriteLayerPtr srcSpriteLayerP)
{
SpritePtr curSpriteP;
SW_ASSERT(srcSpriteLayerP != NULL);
while ((curSpriteP = SWGetNextSprite(srcSpriteLayerP, NULL)) != NULL)
{
SWRemoveSprite(curSpriteP);
}
}
///--------------------------------------------------------------------------------------
// SWDisposeAllSpritesInLayer
///--------------------------------------------------------------------------------------
SW_FUNC void SWDisposeAllSpritesInLayer(
SpriteLayerPtr spriteLayerP)
{
SpritePtr curSpriteP, nextSpriteP;
SW_ASSERT(spriteLayerP != NULL);
curSpriteP = spriteLayerP->headSpriteP;
// iterate through the sprites in this layer
while (curSpriteP != NULL)
{
nextSpriteP = curSpriteP->nextSpriteP;
SWRemoveSprite(curSpriteP);
SWDisposeSprite(&curSpriteP);
curSpriteP = nextSpriteP;
}
}
///--------------------------------------------------------------------------------------
// SWCountNumSpritesInLayer
///--------------------------------------------------------------------------------------
SW_FUNC short SWCountNumSpritesInLayer(
SpriteLayerPtr spriteLayerP)
{
SpritePtr curSpriteP;
short numSprites = 0;
SW_ASSERT(spriteLayerP != NULL);
curSpriteP = spriteLayerP->headSpriteP;
// iterate through the sprites in this layer
while (curSpriteP != NULL)
{
numSprites++;
curSpriteP = curSpriteP->nextSpriteP;
}
return numSprites;
}
///--------------------------------------------------------------------------------------
// SWSwapSprite
///--------------------------------------------------------------------------------------
SW_FUNC OSErr SWSwapSprite(
SpritePtr srcSpriteP,
SpritePtr dstSpriteP)
{
SpriteLayerPtr spriteLayerP;
register SpritePtr swapSpriteP;
OSErr err = noErr;
SW_ASSERT(srcSpriteP != NULL && dstSpriteP != NULL);
spriteLayerP = srcSpriteP->parentSpriteLayerP;
if (spriteLayerP != dstSpriteP->parentSpriteLayerP || spriteLayerP == NULL)
{
err = kBadParameterErr;
SWSetStickyIfError( err );
return err;
}
// adjacent Sprites are a special case
if ( srcSpriteP->nextSpriteP == dstSpriteP ||
dstSpriteP->nextSpriteP == srcSpriteP )
{
if ( srcSpriteP->nextSpriteP == dstSpriteP )
{
if ( srcSpriteP->prevSpriteP != NULL )
(srcSpriteP->prevSpriteP)->nextSpriteP = dstSpriteP;
if ( dstSpriteP->nextSpriteP != NULL )
(dstSpriteP->nextSpriteP)->prevSpriteP = srcSpriteP;
dstSpriteP->prevSpriteP = srcSpriteP->prevSpriteP;
srcSpriteP->nextSpriteP = dstSpriteP->nextSpriteP;
dstSpriteP->nextSpriteP = srcSpriteP;
srcSpriteP->prevSpriteP = dstSpriteP;
}
else
{
if ( dstSpriteP->prevSpriteP != NULL )
(dstSpriteP->prevSpriteP)->nextSpriteP = srcSpriteP;
if ( srcSpriteP->nextSpriteP != NULL )
(srcSpriteP->nextSpriteP)->prevSpriteP = dstSpriteP;
srcSpriteP->prevSpriteP = dstSpriteP->prevSpriteP;
dstSpriteP->nextSpriteP = srcSpriteP->nextSpriteP;
srcSpriteP->nextSpriteP = dstSpriteP;
dstSpriteP->prevSpriteP = srcSpriteP;
}
}
else
{
if ( srcSpriteP->prevSpriteP != NULL && dstSpriteP->prevSpriteP != NULL )
{
swapSpriteP = (srcSpriteP->prevSpriteP)->nextSpriteP;
(srcSpriteP->prevSpriteP)->nextSpriteP =
(dstSpriteP->prevSpriteP)->nextSpriteP;
(dstSpriteP->prevSpriteP)->nextSpriteP = swapSpriteP;
}
if ( srcSpriteP->nextSpriteP != NULL && dstSpriteP->nextSpriteP != NULL )
{
swapSpriteP = (srcSpriteP->nextSpriteP)->prevSpriteP;
(srcSpriteP->nextSpriteP)->prevSpriteP =
(dstSpriteP->nextSpriteP)->prevSpriteP;
(dstSpriteP->nextSpriteP)->prevSpriteP = swapSpriteP;
}
swapSpriteP = srcSpriteP->nextSpriteP;
srcSpriteP->nextSpriteP = dstSpriteP->nextSpriteP;
dstSpriteP->nextSpriteP = swapSpriteP;
swapSpriteP = srcSpriteP->prevSpriteP;
srcSpriteP->prevSpriteP = dstSpriteP->prevSpriteP;
dstSpriteP->prevSpriteP = swapSpriteP;
}
if (srcSpriteP->nextSpriteP == NULL)
{
spriteLayerP->tailSpriteP = srcSpriteP;
}
else if (srcSpriteP->prevSpriteP == NULL)
{
spriteLayerP->headSpriteP = srcSpriteP;
}
if (dstSpriteP->nextSpriteP == NULL)
{
spriteLayerP->tailSpriteP = dstSpriteP;
}
else if (dstSpriteP->prevSpriteP == NULL)
{
spriteLayerP->headSpriteP = dstSpriteP;
}
return noErr;
}
///--------------------------------------------------------------------------------------
// SWInsertSpriteAfterSprite
///--------------------------------------------------------------------------------------
SW_FUNC OSErr SWInsertSpriteAfterSprite(
SpritePtr newSpriteP,
SpritePtr dstSpriteP)
{
SpriteLayerPtr spriteLayerP;
OSErr err = noErr;
SW_ASSERT(newSpriteP != NULL && dstSpriteP != NULL);
spriteLayerP = dstSpriteP->parentSpriteLayerP;
if (newSpriteP->parentSpriteLayerP != NULL)
err = kSpriteAlreadyInLayer;
if (err == noErr)
{
if ( dstSpriteP->nextSpriteP != NULL )
(dstSpriteP->nextSpriteP)->prevSpriteP = newSpriteP;
newSpriteP->nextSpriteP = dstSpriteP->nextSpriteP;
dstSpriteP->nextSpriteP = newSpriteP;
newSpriteP->prevSpriteP = dstSpriteP;
if (newSpriteP->nextSpriteP == NULL)
{
spriteLayerP->tailSpriteP = newSpriteP;
}
// mark the sprite to be drawn, in case the sprite changed tile layers
newSpriteP->needsToBeDrawn = true;
newSpriteP->parentSpriteLayerP = spriteLayerP;
}
SWSetStickyIfError( err );
return err;
}
///--------------------------------------------------------------------------------------
// SWInsertSpriteBeforeSprite
///--------------------------------------------------------------------------------------
SW_FUNC OSErr SWInsertSpriteBeforeSprite(
SpritePtr newSpriteP,
SpritePtr dstSpriteP)
{
SpriteLayerPtr spriteLayerP;
OSErr err = noErr;
SW_ASSERT(newSpriteP != NULL && dstSpriteP != NULL);
spriteLayerP = dstSpriteP->parentSpriteLayerP;
if (newSpriteP->parentSpriteLayerP != NULL)
err = kSpriteAlreadyInLayer;
if (err == noErr)
{
if ( dstSpriteP->prevSpriteP != NULL )
(dstSpriteP->prevSpriteP)->nextSpriteP = newSpriteP;
newSpriteP->prevSpriteP = dstSpriteP->prevSpriteP;
dstSpriteP->prevSpriteP = newSpriteP;
newSpriteP->nextSpriteP = dstSpriteP;
if (newSpriteP->prevSpriteP == NULL)
{
spriteLayerP->headSpriteP = newSpriteP;
}
// mark the sprite to be drawn, in case the sprite changed tile layers
newSpriteP->needsToBeDrawn = true;
newSpriteP->parentSpriteLayerP = spriteLayerP;
}
SWSetStickyIfError( err );
return err;
}
///--------------------------------------------------------------------------------------
// SWGetNextSprite
///--------------------------------------------------------------------------------------
SW_FUNC SpritePtr SWGetNextSprite(
SpriteLayerPtr spriteLayerP,
SpritePtr curSpriteP)
{
SW_ASSERT(spriteLayerP != NULL);
return (curSpriteP == NULL) ? spriteLayerP->headSpriteP : curSpriteP->nextSpriteP;
}
///--------------------------------------------------------------------------------------
// SWLockSpriteLayer
///--------------------------------------------------------------------------------------
SW_FUNC void SWLockSpriteLayer(
SpriteLayerPtr spriteLayerP)
{
SpritePtr curSpriteP;
SW_ASSERT(spriteLayerP != NULL);
curSpriteP = spriteLayerP->headSpriteP;
while (curSpriteP != NULL)
{
SWLockSprite(curSpriteP);
curSpriteP = curSpriteP->nextSpriteP;
}
}
///--------------------------------------------------------------------------------------
// SWUnlockSpriteLayer
///--------------------------------------------------------------------------------------
SW_FUNC void SWUnlockSpriteLayer(
SpriteLayerPtr spriteLayerP)
{
SpritePtr curSpriteP;
SW_ASSERT(spriteLayerP != NULL);
curSpriteP = spriteLayerP->headSpriteP;
while (curSpriteP != NULL)
{
SWUnlockSprite(curSpriteP);
curSpriteP = curSpriteP->nextSpriteP;
}
}
///--------------------------------------------------------------------------------------
// SWCollideSpriteLayer
///--------------------------------------------------------------------------------------
SW_FUNC void SWCollideSpriteLayer(
SpriteWorldPtr spriteWorldP,
SpriteLayerPtr srcSpriteLayerP,
SpriteLayerPtr dstSpriteLayerP)
{
SpritePtr srcSpriteP, nextSrcSpriteP;
SpritePtr dstSpriteP, nextDstSpriteP;
Rect sectRect;
SW_ASSERT(spriteWorldP != NULL);
SW_ASSERT(srcSpriteLayerP != NULL && dstSpriteLayerP != NULL);
// Don't check for collisions unless the frame has been processed!
if (!spriteWorldP->frameHasOccurred)
return;
srcSpriteP = srcSpriteLayerP->headSpriteP;
while (srcSpriteP != NULL)
{
dstSpriteP = dstSpriteLayerP->headSpriteP;
nextSrcSpriteP = srcSpriteP->nextSpriteP;
while (dstSpriteP != NULL)
{
nextDstSpriteP = dstSpriteP->nextSpriteP;
if (srcSpriteP != dstSpriteP)
{
// are the sprite’s rectangles overlapping?
if ((srcSpriteP->destFrameRect.top < dstSpriteP->destFrameRect.bottom) &&
(srcSpriteP->destFrameRect.bottom > dstSpriteP->destFrameRect.top) &&
(srcSpriteP->destFrameRect.left < dstSpriteP->destFrameRect.right) &&
(srcSpriteP->destFrameRect.right > dstSpriteP->destFrameRect.left))
{
// call the source sprite’s collision routine
if (srcSpriteP->spriteCollideProc != NULL)
{
sectRect.left =
SW_MAX(srcSpriteP->destFrameRect.left, dstSpriteP->destFrameRect.left);
sectRect.top =
SW_MAX(srcSpriteP->destFrameRect.top, dstSpriteP->destFrameRect.top);
sectRect.right =
SW_MIN(srcSpriteP->destFrameRect.right, dstSpriteP->destFrameRect.right);
sectRect.bottom =
SW_MIN(srcSpriteP->destFrameRect.bottom, dstSpriteP->destFrameRect.bottom);
(*srcSpriteP->spriteCollideProc)(srcSpriteP, dstSpriteP, §Rect);
}
}
}
// If the nextDstSpriteP has been removed, we must start over again
if (nextDstSpriteP != NULL && nextDstSpriteP->spriteRemoval != kSWDontRemoveSprite)
dstSpriteP = dstSpriteLayerP->headSpriteP;
else
dstSpriteP = nextDstSpriteP;
}
// If the nextSrcSpriteP has been removed, we must start over again
if (nextSrcSpriteP != NULL && nextSrcSpriteP->spriteRemoval != kSWDontRemoveSprite)
srcSpriteP = srcSpriteLayerP->headSpriteP;
else
srcSpriteP = nextSrcSpriteP;
}
}
///--------------------------------------------------------------------------------------
// SWPauseSpriteLayer
///--------------------------------------------------------------------------------------
SW_FUNC void SWPauseSpriteLayer(
SpriteLayerPtr spriteLayerP)
{
SW_ASSERT(spriteLayerP != NULL);
spriteLayerP->isPaused = true;
}
///--------------------------------------------------------------------------------------
// SWUnpauseSpriteLayer
///--------------------------------------------------------------------------------------
SW_FUNC void SWUnpauseSpriteLayer(
SpriteLayerPtr spriteLayerP)
{
SW_ASSERT(spriteLayerP != NULL);
spriteLayerP->isPaused = false;
}
///--------------------------------------------------------------------------------------
// SWFindSpriteByPoint
///--------------------------------------------------------------------------------------
SW_FUNC SpritePtr SWFindSpriteByPoint(
SpriteLayerPtr spriteLayerP,
SpritePtr startSpriteP,
Point testPoint)
{
SpritePtr curSpriteP;
SW_ASSERT(spriteLayerP != NULL);
curSpriteP = (startSpriteP == NULL) ? spriteLayerP->tailSpriteP : startSpriteP;
// note that we traverse the sprites in reverse order
// since this will make the most sense if we are
// looking for a sprite that was clicked
while ((curSpriteP != NULL) && !SWIsPointInSprite(curSpriteP, testPoint))
{
curSpriteP = curSpriteP->prevSpriteP;
}
return curSpriteP;
}